home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -seriously_amiga- / shareware / programming / c / amivogl-mdev / amivogl-mdev.lha / drivers / grx.c < prev    next >
C/C++ Source or Header  |  1994-04-15  |  13KB  |  647 lines

  1. /*
  2.  * GRX driver for VOGL c1993 by Gary Murphy (garym@virtual.rose.utoronto.ca)
  3.  * 
  4.  * To compile:
  5.  * 
  6.  * 1) add GRX to device.c and mash-up your makefiles for MsDOS 2) compile with
  7.  * DOBJ=-DPOSTSCRIPT -DHPGL -DGRX and MFLAGS=-O2
  8.  * 
  9.  * To run:
  10.  * 
  11.  * set VDEVICE=grx
  12.  * 
  13.  * grateful thanks to Lance Norskog (thinman@netcom.com) and Bernie Kirby
  14.  * (bernie@ecr.mu.oz.au) --- should either of you be in my neighbourhood, my
  15.  * offer of an Ice Beer is still open! (Things in #ifdef BLART disabled by
  16.  * bernie...)
  17.  */
  18. #undef VOGLE
  19.  
  20. #include <stdio.h>
  21. #undef DBG
  22. #ifdef DBG
  23. FILE    *dfp = NULL;
  24. #endif
  25. #include <assert.h>
  26.  
  27. #include <stdlib.h>
  28. #include <memory.h>
  29. #include <grx.h>
  30. #include <mousex.h>
  31.  
  32. #define MSG( m ) fprintf(stderr, "\n%s: %d: %s", __FILE__, __LINE__, (m))
  33. #define ERROR1( m, p ) fprintf(stderr, "\n%s: %d: " m, __FILE__, __LINE__, (p))
  34.  
  35. #ifdef VOGLE
  36. #include    "vogle.h"
  37. #else
  38. #include    "vogl.h"
  39. #endif
  40.  
  41. #ifndef TRUE
  42. #define TRUE    1
  43. #endif
  44.  
  45. #ifndef FALSE
  46. #define FALSE    0
  47. #endif
  48.  
  49. #define MAXCOLOR 256
  50.  
  51. static struct {
  52.  
  53.     GR_graphics_modes old_mode;
  54.  
  55.     int             width, height, planes;
  56.     unsigned        scrsize;/* size of buffer in long words */
  57.     GrContext      *cbuf;    /* current context */
  58.     GrContext      *fbuf;
  59.     GrContext      *bbuf;
  60.  
  61.     int             palette[8];
  62.  
  63.     GrLineOption    lopt;    /* pen drawing options */
  64.     int             fg;    /* foreground/background colours */
  65.     int             bg;
  66.  
  67.     int             has_mouse;
  68.  
  69.     GrFont         *font;    /* Current font */
  70.     GrFont         *lfont;    /* Preloaded small font */
  71.     GrFont         *sfont;    /* Preloaded large font */
  72.     char           *fname;    /* Fontname */
  73.     GrTextOption   to;    /* Other text stuff */
  74.  
  75.     int             cx;
  76.     int             cy;
  77.  
  78. } grx;
  79.  
  80. /*
  81.  * access functions: *
  82.  * 
  83. /* I'm going to need this to fudge in stereo graphics ...
  84.  */
  85.  
  86. GrContext * setBackBuffer(GrContext * newBB)
  87. {
  88.     GrContext      *oldBB = grx.bbuf;
  89.     assert(newBB != NULL);
  90.  
  91.     grx.bbuf = newBB;
  92.     return oldBB;
  93. }
  94.  
  95. static int grx_init(void)
  96. {
  97. #ifdef DBG
  98.     dfp = fopen("grx.dbg", "w");
  99. #endif
  100.     grx.old_mode = GrCurrentMode();
  101.     GrSetMode(GR_default_graphics);
  102.  
  103. #ifndef VOGLE
  104.     vdevice.devname = "Grx";
  105. #endif
  106.  
  107.     /* set the VOGL device */
  108.     vdevice.sizeX = GrSizeY();    /* square max, was GrScreenX(); */
  109.     vdevice.sizeY = GrSizeY();
  110.  
  111.     grx.width = vdevice.sizeSx = GrScreenX();
  112.     grx.height = vdevice.sizeSy = GrScreenY();
  113.     grx.planes = vdevice.depth = GrNumPlanes();
  114.  
  115.     grx.scrsize = (GrPlaneSize(grx.width, grx.height) * grx.planes) / sizeof(long);
  116.  
  117.     /* setup default palette */
  118.     GrSetRGBcolorMode();
  119.     grx.lopt.lno_color = grx.fg = GrWhite();
  120.     grx.bg = GrBlack();
  121.  
  122.     grx.palette[BLACK] = GrAllocColor(0, 0, 0);
  123.     grx.palette[RED] = GrAllocColor(255, 0, 0);
  124.     grx.palette[GREEN] = GrAllocColor(0, 255, 0);
  125.     grx.palette[YELLOW] = GrAllocColor(255, 255, 0);
  126.     grx.palette[BLUE] = GrAllocColor(0, 0, 255);
  127.     grx.palette[MAGENTA] = GrAllocColor(255, 0, 255);
  128.     grx.palette[CYAN] = GrAllocColor(0, 255, 255);
  129.     grx.palette[WHITE] = GrAllocColor(255, 255, 255);
  130.  
  131.     /*
  132.      * setup back/front buffers: frontbuffer is the current screen, back
  133.      * is a ram context
  134.      */
  135.     grx.cbuf = grx.fbuf = GrSaveContext(NULL);
  136.     grx.bbuf = NULL;
  137.  
  138.     /* initialize mouse */
  139.     if ((grx.has_mouse = MouseDetect()) == TRUE) {
  140.         /* dare I do interrupts? ... */
  141.         MouseEventMode(1);
  142.         MouseInit();
  143.  
  144.         /* no keyboard (use getch) */
  145.         MouseEventEnable(0, 1);
  146.  
  147.         /* cheezy mouse speed algorithm (blame Lance for the pun) */
  148.         if (grx.width * grx.height < 100000)
  149.             MouseSetSpeed(6);
  150.         else if (grx.width * grx.height < 200000)
  151.             MouseSetSpeed(4);
  152.         else if (grx.width * grx.height < 500000)
  153.             MouseSetSpeed(3);
  154.         else
  155.             MouseSetSpeed(2);
  156.  
  157.         MouseWarp(1, 1);
  158.         MouseDisplayCursor();
  159.     };
  160.  
  161.     /* initial drawing style to thin solid lines */
  162.     grx.lopt.lno_width = 1;
  163.     grx.lopt.lno_pattlen = 0;
  164.     grx.lopt.lno_dashpat = NULL;
  165.     /* load initial fonts */
  166.     if (getenv("GRXFONT") == NULL)
  167.         GrSetFontPath("fonts");
  168.  
  169.     grx.font = grx.sfont = GrLoadFont(vdevice.dev.small);
  170. #ifdef DBG
  171.     if (!grx.font) {
  172.         fprintf(dfp, "GrLoadFont failed");
  173.         fflush(dfp);
  174.     }
  175. #endif
  176.  
  177.     grx.lfont = GrLoadFont(vdevice.dev.large);
  178. #ifdef DBG
  179.     if (!grx.lfont) {
  180.         fprintf(dfp, "GrLoadFont failed");
  181.         fflush(dfp);
  182.     }
  183. #endif
  184.  
  185.     grx.to.txo_font = grx.font;
  186.     grx.to.txo_xmag = grx.to.txo_ymag = 1;
  187.     grx.to.txo_direct = GR_TEXT_RIGHT;
  188.     grx.to.txo_xalign = grx.to.txo_xalign = GR_ALIGN_DEFAULT;
  189.     grx.to.txo_fgcolor = 0;
  190.  
  191.     grx.fname = vdevice.dev.small;
  192.     vdevice.hwidth = 8.0;
  193.     vdevice.hheight = 8.0;
  194.  
  195.     return (1);
  196. }
  197.  
  198. /*
  199.  * grx_frontbuffer, grx_backbuffer, grx_swapbuffers
  200.  * 
  201.  */
  202. static int grx_frontbuffer(void)
  203. {
  204.     grx.cbuf = grx.fbuf;
  205.     GrSetContext(grx.fbuf);
  206.     return (0);
  207. }
  208.  
  209. static int grx_backbuffer(void)
  210. {
  211.     /* if they want a backbuffer, we'd better make one ... */
  212.  
  213.     if (grx.bbuf == NULL)
  214.         grx.bbuf = GrCreateContext(GrSizeX(), GrSizeY(), NULL, NULL);
  215.  
  216.     assert(grx.bbuf != NULL);
  217.  
  218.     grx.cbuf = grx.bbuf;
  219.     GrSetContext(grx.bbuf);
  220.     return (0);
  221. }
  222.  
  223. static int grx_swapbuffers(void)
  224. {
  225.     if (grx.cbuf == grx.fbuf)
  226.         grx_backbuffer();
  227.     else {
  228.         /*
  229.          * there are rumours of a portable VGA backbuffer using VESA
  230.          * but I've yet to track it down.
  231.          * 
  232.          * the following copies by long words from back to front buffer
  233.          * modify this for regions by triming the first x-limit and
  234.          * y-limit and upping the pointers to the start of your
  235.          * subcontext
  236.          */
  237.  
  238.         MouseEraseCursor();
  239.  
  240.         /* WARNING WILL ROBINSON - WARNING WILL ROBINSON */
  241.         /*
  242.          * We're using the NC version so I can copy a 2W by H/2
  243.          * backbuffer in my stereo graphics 'interlaced' mode
  244.          */
  245.  
  246.         GrBitBltNC(grx.fbuf, 0, 0,
  247.                grx.bbuf, 0, 0,
  248.                grx.bbuf->gc_xmax, grx.bbuf->gc_ymax, GrWRITE);
  249.  
  250.         MouseDisplayCursor();
  251.  
  252.  
  253.     }
  254.  
  255.     return (0);
  256. }
  257.  
  258. #ifdef VOGLE
  259. /*
  260.  * grx_vclear
  261.  * 
  262.  * Clear the screen to current colour
  263.  */
  264. int grx_vclear(void)
  265. {
  266.     grx.to.txo_bgcolor = grx.fg;
  267.     GrClearContext(grx.fg);
  268.  
  269. }
  270.  
  271. #else
  272.  
  273. /*
  274.  * grx_vclear
  275.  * 
  276.  * Clear the viewport to current colour
  277.  */
  278. static int grx_vclear(void)
  279. {
  280.     unsigned int    vw = vdevice.maxVx - vdevice.minVx;
  281.     unsigned int    vh = vdevice.maxVy - vdevice.minVy;
  282.  
  283.     grx.to.txo_bgcolor = grx.fg;
  284.     if ((vdevice.sizeSx == vw) && (vdevice.sizeSy == vh)) {
  285.         GrClearContext(grx.fg);    /* full screen */
  286.     } else
  287.         GrFilledBox(
  288.                 vdevice.minVx,
  289.                 vdevice.sizeSy - vdevice.maxVy,
  290.                 grx.width,
  291.                 grx.height,
  292.                 grx.fg);
  293.  
  294.     return (1);
  295. }
  296.  
  297. #endif
  298.  
  299. /*
  300.  * grx_exit
  301.  * 
  302.  * Sets the display back to text mode.
  303.  */
  304. static grx_exit(void)
  305. {
  306.     MouseUnInit();        /* disable mouse/keyboard interrupts */
  307.  
  308.     GrSetMode(grx.old_mode);
  309.     GrDestroyContext(grx.bbuf);
  310.  
  311.     return (1);
  312. }
  313.  
  314. static int grx_sync(void)
  315. {
  316. };
  317.  
  318. static int noop(void)
  319. {
  320.     return (-1);
  321. }
  322.  
  323. /*
  324.  * grx_font : load either of the fonts
  325.  */
  326. static int grx_font(char *name)
  327. {
  328. #ifdef DBG
  329.     fprintf(dfp, "fontname=%s\n", name);
  330.     fflush(dfp);
  331. #endif
  332.     /*
  333.      * Hacky way to quicky test for small or large font
  334.      * ... see of they are the same pointers.... this
  335.      * assumes that they have been called from the main
  336.      * library routine with *vdevice.Vfont(vdevice.smallfont);
  337.      */
  338.     if (name == vdevice.dev.small) {
  339.         grx.font = grx.sfont;
  340.         grx.to.txo_font = grx.font;
  341.         vdevice.hheight = grx.font->fnt_height;
  342.         vdevice.hwidth = grx.font->fnt_width;
  343.         grx.fname = name;
  344. #ifdef DBG
  345.         fprintf(dfp, "w, h: %f %f\n", vdevice.hheight, vdevice.hwidth);
  346.         fflush(dfp);
  347. #endif
  348.         return(1);
  349.     } else if (name == vdevice.dev.large) {
  350.         grx.font = grx.lfont;
  351.         grx.to.txo_font = grx.font;
  352.         vdevice.hheight = grx.font->fnt_height;
  353.         vdevice.hwidth = grx.font->fnt_width;
  354.         grx.fname = name;
  355. #ifdef DBG
  356.         fprintf(dfp, "w, h: %f %f\n", vdevice.hheight, vdevice.hwidth);
  357.         fflush(dfp);
  358. #endif
  359.         return(1);
  360.     } else
  361.  
  362.     /* 
  363.      * It must be a completely different font (ala vogle possibility).
  364.      */
  365.     if (strcmp(name, grx.fname)) {
  366.         if (grx.font != grx.sfont && grx.font != grx.lfont)
  367.             GrUnloadFont(grx.font);
  368.  
  369.         if (grx.fname) {
  370.             free(grx.fname);
  371.             grx.fname = (char *)malloc(strlen(name) + 1);
  372.             strcpy(grx.fname, name);
  373.         }
  374.  
  375.         if (!(grx.font = GrLoadFont(name))) {
  376.             return(0);
  377.         }
  378.  
  379.         grx.to.txo_font = grx.font;
  380.  
  381.         vdevice.hheight = grx.font->fnt_height;
  382.         vdevice.hwidth = grx.font->fnt_width;
  383. #ifdef DBG
  384.         fprintf(dfp, "w, h: %f %f\n", vdevice.hheight, vdevice.hwidth);
  385.         fflush(dfp);
  386. #endif
  387.     }
  388.  
  389.     return (1);
  390. }
  391.  
  392. static int grx_char(int c)
  393. {
  394.     GrDrawChar(c, vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy - vdevice.hheight, &grx.to);
  395.     vdevice.cpVx += vdevice.hwidth;
  396.  
  397.     return (1);
  398. };
  399.  
  400. static int grx_string(char *s)
  401. {
  402.     int    len = strlen(s);
  403.     GrDrawString(s, len, vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy - vdevice.hheight, &grx.to);
  404.     vdevice.cpVx += vdevice.hwidth * len;
  405.     return (1);
  406. }
  407.  
  408.  
  409. /*
  410.  * Everything is supposed to have been through the higher up clippers in
  411.  * vogl.. so no need to clip here..
  412.  * 
  413.  * Draw a solid 1 pixel wide line... libgrx checks for horizontal and vertical
  414.  * lines for us.
  415.  */
  416. static int grx_solid(
  417.   int x,
  418.   int y)
  419. {
  420.  
  421.     GrLineNC(x, vdevice.sizeSy - y,
  422.          vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy,
  423.          grx.fg
  424.     );
  425.  
  426.     vdevice.cpVx = x;
  427.     vdevice.cpVy = y;
  428.  
  429.     return (0);
  430. }
  431.  
  432. /*
  433.  * Draw a patterned and/or > 1 pixel wide line. (Waiting for libgrx to
  434.  * actually implement this...)
  435.  */
  436. static int grx_pattern(
  437.   int x,
  438.   int y)
  439. {
  440.     GrCustomLine(vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy,
  441.              x, vdevice.sizeSy - y,
  442.              &grx.lopt
  443.     );
  444.  
  445.     vdevice.cpVx = x;
  446.     vdevice.cpVy = y;
  447.  
  448.     return (0);
  449. };
  450.  
  451. static int grx_colour(int i)
  452. {
  453.  
  454.     if (i < MAXCOLOR)
  455.         grx.fg = grx.palette[i];    /* for now */
  456.     else
  457.         grx.fg = GrBlack();
  458.  
  459.     grx.lopt.lno_color = grx.fg;
  460.  
  461.     grx.to.txo_fgcolor = grx.fg;
  462.     return (0);
  463. };
  464.  
  465. /*
  466.  * grx_mapcolor
  467.  * 
  468.  * change index i in the color map to the appropriate r, g, b, value.
  469.  */
  470. static int grx_mapcolor(
  471.   int c,
  472.   int r,
  473.   int g,
  474.   int b)
  475. {
  476.     int             j;
  477.  
  478.     if (c >= MAXCOLOR || vdevice.depth == 1)
  479.         return (-1);
  480.  
  481.     grx.palette[c] = GrAllocColor(r, g, b);
  482.  
  483. }
  484.  
  485.  
  486. static int grx_fill(
  487.   int sides,
  488.   int *x,
  489.   int *y)
  490. {
  491.     int             i, j;
  492.     int             points[sides][2];
  493.  
  494.     for (i = 0; i < sides; i++) {
  495.         points[i][0] = x[i];
  496.         points[i][1] = grx.height - y[i];
  497.     }
  498.  
  499.     GrFilledPolygon(sides, points, grx.fg);
  500.  
  501.     return (0);
  502. };
  503.  
  504. static int grx_checkkey(void)
  505. {
  506.     char            c;
  507.  
  508.     if (kbhit()) {
  509.         if ((c = getkey()) == 3) {    /* control-c */
  510.             grx_exit();
  511.             /* don't call vexit(), avoid back-refs */
  512.             exit(0);
  513.         } else
  514.             return c;
  515.     } else
  516.         return 0;
  517. }
  518.  
  519. static int grx_locator(
  520.   int *x,
  521.   int *y)
  522. {
  523.     MouseEvent      mEv;
  524.     static          ox = 0, oy = 0, obuttons = 0;
  525.  
  526.     if (!grx.has_mouse) {
  527.         *x = *y = 0;
  528.         return (-1);
  529.     }
  530.     /*
  531.      * if (MousePendingEvent()) {
  532.      */
  533.     MouseGetEvent(M_MOTION | M_BUTTON_CHANGE | M_POLL, &mEv);
  534.  
  535.     if (mEv.flags & M_MOTION) {
  536.         ox = mEv.x;
  537.         oy = vdevice.sizeSy - mEv.y;
  538.     }
  539.     /*
  540.      * HACK... the RIGHT button is the second button and we want it to
  541.      * return 2...
  542.      */
  543.  
  544.     if (mEv.flags & M_BUTTON_CHANGE) {
  545.         obuttons = ((mEv.buttons & M_LEFT) ? 1 : 0) |
  546.             ((mEv.buttons & M_MIDDLE) ? 2 : 0) |
  547.             ((mEv.buttons & M_RIGHT) ? 2 : 0);
  548.     }
  549.     /*
  550.      * }
  551.      */
  552.  
  553.     *x = ox;
  554.     *y = oy;
  555.  
  556.     return (obuttons);
  557. }
  558.  
  559. static int grx_lwidth(int w)
  560. {
  561.  
  562.     grx.lopt.lno_width = w;
  563.     if (w == 1 && grx.lopt.lno_pattlen == 0)
  564.         vdevice.dev.Vdraw = grx_solid;
  565.     else
  566.         vdevice.dev.Vdraw = grx_pattern;
  567. }
  568.  
  569. static int grx_lstyle(int s)
  570. {
  571.  
  572.     static unsigned char dashes[16];
  573.     unsigned        ls = s;
  574.     int             i, n, a, b;
  575.  
  576.     if (grx.lopt.lno_width == 1 && (ls == 0 || ls == 0xffff)) {
  577.         vdevice.dev.Vdraw = grx_solid;
  578.         grx.lopt.lno_pattlen = 0;
  579.         return;
  580.     }
  581.     for (i = 0; i < 16; i++)
  582.         dashes[i] = 0;
  583.  
  584. #define    ON    1
  585. #define    OFF    0
  586.  
  587.     a = b = OFF;
  588.     if (ls & (1 << 0))
  589.         a = b = ON;
  590.  
  591.     n = 0;
  592.     for (i = 0; i < 16; i++) {    /* Over 16 bits */
  593.         if (ls & (1 << i))
  594.             a = ON;
  595.         else
  596.             a = OFF;
  597.  
  598.         if (a != b) {
  599.             b = a;
  600.             n++;
  601.         }
  602.         dashes[n]++;
  603.     }
  604.  
  605.     grx.lopt.lno_pattlen = 16;
  606.     grx.lopt.lno_dashpat = dashes;
  607.     vdevice.dev.Vdraw = grx_pattern;
  608. }
  609.  
  610. static DevEntry grxdev = {
  611.     "grx",
  612.     "@:pc8x16.fnt",        /* Large font */
  613.     "@:pc8x8.fnt",        /* Small font */
  614.     grx_backbuffer,        /* backbuffer */
  615.     grx_char,        /* hardware char */
  616.     grx_checkkey,        /* keyhit */
  617.     grx_vclear,        /* clear viewport to current colour */
  618.     grx_colour,        /* set current colour */
  619.     grx_solid,        /* draw line */
  620.     grx_exit,        /* close graphics & exit */
  621.     grx_fill,        /* fill polygon */
  622.     grx_font,        /* set hardware font */
  623.     grx_frontbuffer,    /* front buffer */
  624.     getkey,            /* wait for and get key */
  625.     grx_init,        /* begin graphics */
  626.     grx_locator,        /* get mouse position */
  627.     grx_mapcolor,        /* map colour (set indices) */
  628. #ifndef VOGLE
  629.     grx_lstyle,        /* set linestyle */
  630. #endif
  631.     grx_lwidth,        /* set line width */
  632.     grx_string,        /* draw string of chars */
  633.     grx_swapbuffers,    /* swap buffers */
  634.     grx_sync        /* sync display */
  635. };
  636.  
  637. /*
  638.  * _grx_devcpy
  639.  * 
  640.  * copy the pc device into vdevice.dev. (as listed in drivers.c)
  641.  */
  642. int _grx_devcpy(void)
  643. {
  644.     vdevice.dev = grxdev;
  645.     return (0);
  646. }
  647.